package com.paper.tiger.easy.rpc.s.client.config;

import com.alibaba.fastjson.JSON;
import com.paper.tiger.easy.rpc.annotation.Remote;
import com.paper.tiger.easy.rpc.core.RegisterData;
import com.paper.tiger.easy.rpc.core.ServerType;
import com.paper.tiger.easy.rpc.core.Stub;
import com.paper.tiger.easy.rpc.s.client.SpringContextSupport;
import com.paper.tiger.easy.rpc.s.client.client.ContextManager;
import com.paper.tiger.easy.rpc.s.client.client.ProxyInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 *
 *
 *
 * @author ZouHaiBo
 * @version 1.0, 2021/6/28 18:12
 * @since JDK 1.8
 */
@Component
public class Tiger implements ApplicationRunner, EnvironmentAware
{
    private static Logger logger = LoggerFactory.getLogger(Tiger.class);

    private static boolean stared = false;

    private Environment environment;

    @Override
    public void run(ApplicationArguments args) throws Exception
    {

        logger.info("执行启动方法");
        if (!stared){
            Map<String, Object> registyMap = SpringContextSupport.getBeansWithAnnotation(Remote.class);

            if (registyMap != null || registyMap.size() != 0)
            {
                // 注册服务到注册中心
                doRegistyCenter(registyMap);

            }
            stared = true;
        }



    }


    private void doRegistyCenter(Map<String, Object> registyMap) {

        String applicationName = environment.getProperty("spring.application.name");

        ContextManager manager = ContextManager.getInstance();
        RegisterData data = new RegisterData();
        data.setType(ServerType.REGISTER_REQUEST.getCode());
        List<Stub> list = new ArrayList<>();
        data.setAppName(applicationName);
        data.setList(list);


        List<Stub> selectlist = new ArrayList<>();

        registyMap.forEach((serviceName,serviceObj)->{

            Class<?> metaClass = serviceObj.getClass();
            if (AopUtils.isAopProxy(serviceObj)){
                 metaClass = AopUtils.getTargetClass(serviceObj);
            }


            Class<?>[] interfaces = metaClass.getInterfaces();
            if (interfaces == null || interfaces.length ==0){
                logger.error("registy error, not specify rpc interface serviceName:{}, ",serviceName);
                return;
            }

            Class<?> interfaceClass = null;
            Remote annotation;
            for (Class<?> anInterface : interfaces)
            {
                annotation = anInterface.getAnnotation(Remote.class);
                if (annotation != null ){
                    interfaceClass = anInterface;
                    break;
                }

            }



            if (interfaceClass == null){
                logger.error("not found interface ");
                return;
            }
            if (serviceObj instanceof Proxy){


                //Proxy proxy = (Proxy) serviceObj;
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(serviceObj);
                // 实现类是自己经过代理实现的，标识该服务需要到注册中心查询
                if (invocationHandler instanceof ProxyInstance){

                    Stub stub = new Stub();
                    stub.setInterfaceClass(interfaceClass);
                    selectlist.add(stub);
                    return ;
                }
            }

            Stub stub = new Stub();
            stub.setInterfaceClass(interfaceClass);
            stub.setServiceId(serviceName);
            stub.setImplClass(metaClass);
            stub.setAppName(applicationName);
            list.add(stub);
        });
        if (list.size() == 0){
            logger.info("can not registy server，because not exist @Remote");
            return;
        }

        if (!CollectionUtils.isEmpty(data.getList())){
            logger.info("registy data: {}", JSON.toJSONString(data));
            manager.sendRegistyMsg(data);
        }
        // 查询服务
        if (!CollectionUtils.isEmpty(selectlist)){
            logger.info("select data: {}", JSON.toJSONString(selectlist));
            doSelectServer(selectlist);
        }
    }

    /**
     *  根据接口查询 注册中心的服务
     * @param stubs
     */
    private void doSelectServer(List<Stub> stubs)
    {
        String serverName = environment.getProperty("spring.application.name");
        RegisterData data = new RegisterData();
        data.setList(stubs);
        data.setType(ServerType.SELECT_REQUEST.getCode());
        data.setAppName(serverName);
        ContextManager manager = ContextManager.getInstance();
        manager.sendRegistyMsg(data);
    }


    @Override
    public void setEnvironment(Environment environment)
    {
        this.environment = environment;
    }
}
